package io.renren.common.listener;

import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.alibaba.fastjson.JSON;
import io.renren.common.utils.Result;
import io.renren.modules.sp.dto.SpMatchAreaLimitDTO;
import io.renren.modules.sp.entity.SpMatchAreaEntity;
import io.renren.modules.sp.entity.SpMatchAreaLimitEntity;
import io.renren.modules.sp.service.SpMatchAreaLimitService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 选手荣誉证书导入
 */
@Slf4j
public class SpMatchAreaLimitImportListener extends AnalysisEventListener<Map<Integer, String>> {

    private Result result;

    private SpMatchAreaLimitService spMatchAreaLimitService;
    /**
     * 每隔5条存储数据库，实际使用中可以3000条，然后清理list ，方便内存回收
     */
    private static final int BATCH_COUNT = 3000;
    private static int PROCESS, TOTAL = 0;
    List<Map<Integer, String>> list;
    Map<Integer, String> headMap;
    String matchId = null;
    List<Map<String,String>> hisList;
    Set<String> matchIds = new TreeSet<>();
    Set<String> itemIds = new TreeSet<>();
    Map<String,Map<String, String>> dataMap = new HashMap<>();
    public SpMatchAreaLimitImportListener(SpMatchAreaLimitService service, Result result, List<Map<Integer, String>> list, List<Map<String,String>> dataList) {
        this.spMatchAreaLimitService = service;
        this.result = result;
        this.list = list;
        for (Map<String, String> map : dataList) {
            String matchName = map.get("match_name");
            String matchItem = map.get("item_name");
            matchIds.add(matchName);
            if(matchItem!=null){
                itemIds.add(matchItem);
            }
            dataMap.put(matchName+"@@"+matchItem,map);
        }
    }

    @Override
    public void invokeHeadMap(Map<Integer, String> map, AnalysisContext context) {
        super.invokeHeadMap(map, context);
        this.headMap = map;
    }

    @Override
    public void invoke(Map<Integer, String>  data, AnalysisContext context) {
        log.info("解析到一条数据:{}", JSON.toJSONString(data));
        PROCESS++;
        list.add(data);
        // 达到BATCH_COUNT了，需要去存储一次数据库，防止数据几万条数据在内存，容易OOM
       /* if (list.size() >= BATCH_COUNT) {
            saveData();
            list.clear();
        }*/
    }

    @Override
    public void doAfterAllAnalysed(AnalysisContext context) {
        saveData();
        TOTAL = 0;
        PROCESS = 0;
        log.info("所有数据解析完成！");
    }

    /**
     * 加上存储数据库
     */
    private void saveData() {
        log.info("{}条数据，开始存储数据库！", list.size());
        //校验数据
        this.validateData();
        //判断有错误消息
        for(Map<Integer, String> item : list){
            String msg = item.get(headMap.size());
            //有错误消息就终止
            if (StringUtils.isNotEmpty(msg)) {
                result.error(msg);
                list.add(headMap);
                return;
            }
        }


        boolean importFlag = true;
        if (!CollectionUtils.isEmpty(list)) {
            //判断表头里有没有错误消息这一列

            for (Map<Integer, String> item : list) {
                String matchName = item.get(0);
                if (!matchIds.contains(matchName)) {
                    if (!"失败原因".equals(headMap.get(headMap.size()-1))) {
                        item.put(headMap.size(), "赛事不存在或者赛事未配置赛项");
                        item.put(headMap.size() + 1, "导入失败");
                    }else{
                        item.put(headMap.size()-1, "赛事不存在或者赛事未配置赛项");
                        item.put(headMap.size(), "导入失败");
                    }
                    importFlag = false;
                    continue;
                }
                StringBuffer sb = new StringBuffer();
                for (int i = 2; i <= headMap.size(); i++) {
                    String matchItem = headMap.get(i);
                    String value = item.get(i);

                    //去掉空格
                    if(StringUtils.isNotEmpty(value)) {
                        value = value.trim();
                    }

                    //空的话直接跳过
                    if (StringUtils.isEmpty(value)) {
                        continue;
                    }

                    if (StringUtils.isNotBlank(value) && !"-".equals(value)) {
                        Map<String, String> data = dataMap.get(matchName + "@@" + matchItem);
                        if (data == null) {
                            sb.append("本赛事未开设" + matchItem + ";");
                            continue;
                        }
                        String matchId = data.get("match_id");
                        String matchItemId = data.get("match_item_id");
                        SpMatchAreaLimitEntity entity = null;
                        if (StringUtils.isNotEmpty(matchId) && StringUtils.isNotEmpty(matchItemId)) {
                            matchId = matchId.replace(",", "");
                            matchItemId = matchItemId.replace(",", "");
                            List<SpMatchAreaLimitEntity> entityList = spMatchAreaLimitService.queryBy(Integer.parseInt(matchId), Integer.parseInt(matchItemId));
                            if (entityList != null && entityList.size() > 0) {
                                entity = entityList.get(0);
                            } else {
                                entity = new SpMatchAreaLimitEntity();
                                entity.setMatchId(Integer.parseInt(matchId));
                                entity.setMatchItemId(Integer.parseInt(matchItemId));
                                entity.setProvince(data.get("province"));
                            }
                            String haveNum = data.get("have_num");
                            if (Integer.valueOf(haveNum) > Integer.valueOf(value)) {
                                sb.append(matchItem + "已经推荐" + haveNum + "人;");

                                continue;
                            }
                            entity.setNum(Integer.parseInt(value));
                            if (entity.getId() == null) {
                                spMatchAreaLimitService.insert(entity);
                            } else {
                                spMatchAreaLimitService.updateById(entity);
                            }
                        }
                    } else {
                        Map<String, String> data = dataMap.get(matchName + "@@" + matchItem);
                        if (data != null) {
                            //删除配置
                            String matchId = data.get("match_id");
                            String matchItemId = data.get("match_item_id");
                            matchId = matchId.replace(",", "");
                            //移除matchItemId里的逗号
                            if (StringUtils.isNotEmpty(matchItemId)) {
                                matchItemId = matchItemId.replace(",", "");

                                List<SpMatchAreaLimitEntity> entityList = spMatchAreaLimitService.queryBy(Integer.parseInt(matchId), Integer.parseInt(matchItemId));
                                if (entityList != null && entityList.size() > 0) {
                                    spMatchAreaLimitService.deleteBatchIds(entityList.stream().map(SpMatchAreaLimitEntity::getId).collect(Collectors.toList()));
                                }
                            }
                        }
                    }

                }
                if (sb.length() > 0) {
                    importFlag = false;
                    if (!"失败原因".equals(headMap.get(headMap.size()-1))) {
                        item.put(headMap.size(), sb.toString());
                        item.put(headMap.size() + 1, "导入失败");
                    }else{
                        item.put(headMap.size()-1, sb.toString());
                        item.put(headMap.size() , "导入失败");
                    }
                }

            }
        }
        if(!importFlag){
            list.add(headMap);
        }
        log.info("存储数据库成功！");
    }

    //校验数据
    private void validateData() {
        //判断最后一列标题是不是『失败原因』

        if (!CollectionUtils.isEmpty(list)) {
            // 行数据处理
            for (Map<Integer, String> item : list) {
                String matchName = item.get(0);
                if (!matchIds.contains(matchName)) {
                    if (!"失败原因".equals(headMap.get(headMap.size()-1))) {
                        item.put(headMap.size(), "赛事不存在或者赛事未配置赛项");
                        item.put(headMap.size() + 1, "导入失败");
                    }else{
                        item.put(headMap.size()-1, "赛事不存在或者赛事未配置赛项");
                        item.put(headMap.size(), "导入失败");
                    }
                    continue;
                }
                StringBuffer sb = new StringBuffer();
                for (int i = 2; i <= headMap.size(); i++) {
                    String matchItem = headMap.get(i);
                    String value = item.get(i);

                    //去掉空格
                    if(StringUtils.isNotEmpty(value)) {
                        value = value.trim();
                    }

                    if (StringUtils.isNotBlank(value) && !"-".equals(value)) {
                        Map<String, String> data = dataMap.get(matchName + "@@" + matchItem);
                        if (data == null) {
                            sb.append("本赛事未开设" + matchItem + ";");
                        }

                        String haveNum = data.get("have_num");
                        if (Integer.valueOf(haveNum) > Integer.valueOf(value)) {
                            sb.append(matchItem + "已推荐" + haveNum + "人;");
                        }
                    }
                }
                if (sb.length() > 0) {
                    if (!"失败原因".equals(headMap.get(headMap.size()-1))) {
                        item.put(headMap.size(), sb.toString());
                        item.put(headMap.size() + 1, "导入失败");
                    }else{
                        item.put(headMap.size()-1, sb.toString());
                        item.put(headMap.size(), "导入失败");
                    }
                }
            }
        }

    }

}
